package frontend.components.other;

import backend.model.base.DBModel;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.OnChangeAjaxBehavior;
import org.apache.wicket.ajax.markup.html.AjaxLink;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.util.ListModel;

import java.util.Collections;
import java.util.List;

public class EntityListAndSearchPanel<DBM extends DBModel> extends Panel {

    public EntityListAndSearchPanel(String id, String panelTitle, String checkboxFilterLabel, final EntityListAndSearchCallback callback) {
        super(id);
        add(new Label("panelTitle", new ResourceModel(panelTitle)));
        WebMarkupContainer searchForm = createSearchForm(callback, checkboxFilterLabel);
        add(searchForm);
    }

    private WebMarkupContainer createSearchForm(final EntityListAndSearchCallback callback, String checkboxFilterLabel) {
        final Form<Void> searchForm = new Form<Void>("searchForm");

        final List<DBM> availableEntities = callback.getAvailableEntities();
        Collections.sort(availableEntities);
        ListModel<DBM> availableEntitiesListModel = new ListModel<DBM>(availableEntities);

        final WebMarkupContainer availableEntitiesContainer = new WebMarkupContainer("availableEntitiesContainer");
        availableEntitiesContainer.setOutputMarkupId(true); // This attribute is necessary for creating the AJAX dependency

        final ListView<DBM> availableEntitiesView = new ListView<DBM>("availableEntities", availableEntitiesListModel) {

            @Override
            protected void populateItem(ListItem<DBM> item) {
                final DBM dbModel = item.getModelObject();

                AjaxLink<Void> entityLink = new AjaxLink<Void>("entityLink") {

                    @Override
                    public void onClick(AjaxRequestTarget target) {
                        callback.onEntitySelected(target, dbModel);
                    }

                };
                entityLink.add(new Label("entityLabel", dbModel.getDisplayLabel()));
                item.add(entityLink);
            }
        };

        final TextField<String> filterTextField = new TextField<String>("searchFilter", new Model<String>(""));
        filterTextField.setOutputMarkupId(true);

        Label showOnlyActiveLabel = new Label("showOnlyActiveLabel", new ResourceModel(checkboxFilterLabel));
        final CheckBox showOnlyActiveCheckBox = new CheckBox("showOnlyActiveCheckBox", new Model<Boolean>());
        showOnlyActiveCheckBox.getModel().setObject(false);

        OnChangeAjaxBehavior filterChangeBehavior = new OnChangeAjaxBehavior() {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                List<DBM> filteredEntities = callback.getFilteredEntities(filterTextField.getValue(), showOnlyActiveCheckBox.getModelObject(), availableEntities);
                availableEntitiesView.setDefaultModelObject(filteredEntities);
                target.add(availableEntitiesContainer); // Defines the component that has to be updated
            }
        };

        // Same instance of behavior cannot be added to two different components
        OnChangeAjaxBehavior showOnlyActiveChangeBehavior = new OnChangeAjaxBehavior() {
            @Override
            protected void onUpdate(AjaxRequestTarget target) {
                List<DBM> filteredEntities = callback.getFilteredEntities(filterTextField.getValue(), showOnlyActiveCheckBox.getModelObject(), availableEntities);
                availableEntitiesView.setDefaultModelObject(filteredEntities);
                target.add(availableEntitiesContainer); // Defines the component that has to be updated
            }
        };

        filterTextField.add(filterChangeBehavior);
        showOnlyActiveCheckBox.add(showOnlyActiveChangeBehavior);

        searchForm.add(filterTextField);
        searchForm.add(showOnlyActiveLabel);
        searchForm.add(showOnlyActiveCheckBox);

        availableEntitiesContainer.add(availableEntitiesView);
        searchForm.add(availableEntitiesContainer);
        return searchForm;
    }
}
